<?php

namespace business\elasticsearch\services;

use business\elasticsearch\models\BigDataContactModel;
use business\elasticsearch\models\BigDataSaasSupplierModel;
use business\elasticsearch\repositories\EsQuery;
use business\elasticsearch\services\dto\ScoreCondition;
use common\utils\ArrayUtils;

class BigDataContactService
{
    /** 联系人列表
     * @param array $companyName
     * @param array $organizingCode
     * @param string $currentCompanyName
     * @param string $currentOrganizingCode
     * @param array $subscriptProvinceCode
     * @param array $subscriptCityCode
     * @param string $isDeveloper
     * @param string $isSupplier
     * @param array $bidKeyword
     * @param array $supplierKeyword
     * @param array $searchKeyword
     * @param string $phoneType
     * @param string $bidOwnerMobile
     * @param array $provinceCode
     * @param array $cityCode
     * @param int $page
     * @param int $pageSize
     * @return array
     */
    public function getRecommend(
        $id = [],
        $companyName = [],
        $organizingCode = [],
        $currentCompanyName = '',
        $currentOrganizingCode = '',
        $subscriptProvinceCode = [],
        $subscriptCityCode = [],
        $isDeveloper = '',
        $isSupplier = '',
        $bidKeyword = [],
        $supplierKeyword = [],
        $searchKeyword = [],
        $phoneType = [],
        $bidOwnerMobile = '',
        $provinceCode = [],
        $cityCode = [],
        $areaCode = [],
        $scoreWeight = '',
        $page = 1,
        $pageSize = 20
    )
    {

        $condition = $this->constructConditionContactRecommend(
            $id,
            $companyName,
            $organizingCode,
            $currentCompanyName,
            $currentOrganizingCode,
            $subscriptProvinceCode,
            $subscriptCityCode,
            $isDeveloper,
            $isSupplier,
            $bidKeyword,
            $supplierKeyword,
            $searchKeyword,
            $phoneType,
            $bidOwnerMobile,
            $provinceCode,
            $cityCode,
            $areaCode,
            $scoreWeight
        );

        $query = BigDataContactModel::find()->query($condition);
//        echo json_encode($query, JSON_UNESCAPED_UNICODE);
//        exit();
        $highlight = [
            'pre_tags' => ['<em class="_high">'],
            'post_tags' => ['</em>'],
            "fields" => [
                "name" => new \stdClass(),
                "company_name" => new \stdClass(),
                "cooperation.title" => new \stdClass(),
            ]
        ];
        $query->highlight($highlight);
        $query->orderBy(['_score' => SORT_DESC, 'data_time' => SORT_DESC,]);

//        $total = $query->count();
        //分页处理
        $query->offset(($page - 1) * $pageSize)->limit($pageSize);
//        $data = $query->asArray()->all();
        $searchData = $query->createCommand()->search();

//        \yii::info("contact-result", json_encode($searchData, JSON_UNESCAPED_UNICODE));
        //数据处理
        $total = 0;
        $list = [];
        if (empty($searchData)) {
            return ['total' => $total, 'list' => $list];
        }
        $data = $searchData["hits"]["hits"];
        $total = $searchData["hits"]["total"];
        foreach ($data as $dk => $dv) {
            $tmp = $dv['_source'];

            if (!empty($dv['highlight'])) {
                foreach ($dv['highlight'] as $key => $value) {
                    $tmp[$key . 'HL'] = isset($value[0]) ? $value[0] : '';
                }
            }

            //处理合作单位:排序、高亮、最多展示2条
            $isKeywordMatch = false;//关键词是否匹配上
            $biddingSubscriptCnt = 0;
            $cooperationSubscriptCnt = 0;
            //案例搜索高亮字段
            $originTitle = isset($tmp['cooperation.titleHL']) ? $tmp['cooperation.titleHL'] : '';
            $highLightTitle = str_replace("<em class=\"_high\">", "", str_replace("</em>", "", $originTitle));

            if (!empty($tmp['cooperation'])) {
                //如果is_developer=0 且 is_supplier=0，则默认为开发商即is_developer=1 。 20231026
                if (empty($isDeveloper) && empty($isSupplier)) {
                    $isDeveloper = 1;
                }

                foreach ($tmp['cooperation'] as $cooperationK => &$cooperationV) {
                    //高亮
                    if ($cooperationV['title'] == $highLightTitle) {
                        $cooperationV['titleHL'] = $originTitle;
                    } else {
                        $cooperationV['titleHL'] = $cooperationV['title'];
                    }
                    $cooperationV['weight'] = 0;
                    if (!empty($isDeveloper) && !empty($bidKeyword)) {
                        $subscriptionCntFlag = false;//标识是否：纳入符合订阅数量
                        foreach ($bidKeyword as $keywordValue) {
                            if (mb_strpos($cooperationV['titleHL'], $keywordValue) !== false && $cooperationV['category'] == '历史招标') {
                                $cooperationV['weight'] += 10;
                                $isKeywordMatch = true;
                                $subscriptionCntFlag = true;
                                //高亮
                                $cooperationV['titleHL'] = str_replace($keywordValue, "<em class=\"_high\">" . $keywordValue . "</em>", $cooperationV['titleHL']);
                            }
                        }
                        if ($subscriptionCntFlag) {
                            $biddingSubscriptCnt += 1;
                        }

                    } elseif (!empty($isSupplier) && !empty($supplierKeyword)) {
                        $subscriptionCntFlag = false;//标识是否：纳入符合订阅数量
                        foreach ($supplierKeyword as $keywordValue) {
                            if (mb_strpos($cooperationV['titleHL'], $keywordValue) !== false && $cooperationV['category'] == '合作案例') {
                                $cooperationV['weight'] += 10;
                                $isKeywordMatch = true;
                                $subscriptionCntFlag = true;
                                //高亮
                                $cooperationV['titleHL'] = str_replace($keywordValue, "<em class=\"_high\">" . $keywordValue . "</em>", $cooperationV['titleHL']);
                            }
                        }
                        if ($subscriptionCntFlag) {
                            $cooperationSubscriptCnt += 1;
                        }

                    }
                    //开发商则历史招标排前面，供应商则合作案例排前面
                    /*if (!empty($isDeveloper) && empty($isSupplier)) {
                        if ($cooperationV['category'] == '历史招标') {
                            $cooperationV['weight'] += 20;
                        }
                    }
                    if (empty($isDeveloper) && !empty($isSupplier)) {
                        if ($cooperationV['category'] == '合作案例') {
                            $cooperationV['weight'] += 20;
                        }
                    }*/
                    if (!empty($isDeveloper) && $cooperationV['category'] == '合作案例') {
                        unset($tmp['cooperation'][$cooperationK]);
                    }
                    if (!empty($isSupplier) && $cooperationV['category'] == '历史招标') {
                        unset($tmp['cooperation'][$cooperationK]);
                    }

                    //高亮字段前置省略
                    $indexTitleHL = mb_strpos($cooperationV['titleHL'], "<em class=\"_high\">");
                    if ($indexTitleHL !== false) {
                        if ($indexTitleHL - 8 > 0) {
                            $cooperationV['titleHL'] = "..." . mb_substr($cooperationV['titleHL'], $indexTitleHL - 8);
                        } else {
                            $cooperationV['titleHL'] = mb_substr($cooperationV['titleHL'], 0);
                        }

                    }

                    $cooperationV = $this->formatCooperation($cooperationV);

                }
                //排序
                array_multisort(array_column($tmp['cooperation'], 'weight'), SORT_DESC, array_column($tmp['cooperation'], 'cooperation_time'), SORT_DESC, $tmp['cooperation']);

                //合作案例做多展示2条
                $newCooperation = [];
                if (!empty($tmp['cooperation'])) {
                    foreach ($tmp['cooperation'] as $cooperationK2 => $cooperationV2) {
                        if ($cooperationK2 <= 1) {
                            $newCooperation[] = $cooperationV2;
                        }
                    }
                    $tmp['cooperation'] = $newCooperation;
                }

            }
            //联系人推荐标签：手机、近1年更新，订阅关键词匹配上
            $lastYearTimeStamp = strtotime("-1 year");
            $tmp['data_time'] = empty($tmp['data_time']) ? '1990-01-01 00:00:00' : $tmp['data_time'];
            if ($page == 1 && $tmp['phone_type'] == '手机' && strtotime($tmp['data_time']) >= $lastYearTimeStamp && $isKeywordMatch && $dk <= 2) {
                $tmp['is_recommend'] = 1;
            }
            //如果是招标负责人
            if ($tmp['phone_number'] == $bidOwnerMobile) {
                $tmp['purchase_owner'] = "招标负责人";
            }
            //符合订阅的招标、合作案例数量
            $tmp['bidding_subscript_cnt'] = $biddingSubscriptCnt;
            $tmp['cooperation_subscript_cnt'] = $cooperationSubscriptCnt;

            $tmp['_score'] = $dv['_score'];
            $tmp = $this->formatContact($tmp);
            $list[] = $tmp;
        }

        return ['total' => $total, 'list' => $list];
    }

    //只取少数字段
    public function getRecommendSingle(
        $id = [],
        $companyName = [],
        $organizingCode = [],
        $currentCompanyName = '',
        $currentOrganizingCode = '',
        $subscriptProvinceCode = [],
        $subscriptCityCode = [],
        $isDeveloper = '',
        $isSupplier = '',
        $bidKeyword = [],
        $supplierKeyword = [],
        $searchKeyword = [],
        $phoneType = '',
        $bidOwnerMobile = '',
        $provinceCode = [],
        $cityCode = [],
        $areaCode = [],
        $scoreWeight = '',
        $page = 1,
        $pageSize = 20,
        $fieldes = []
    )
    {

        $condition = $this->constructConditionContactRecommend(
            $id,
            $companyName,
            $organizingCode,
            $currentCompanyName,
            $currentOrganizingCode,
            $subscriptProvinceCode,
            $subscriptCityCode,
            $isDeveloper,
            $isSupplier,
            $bidKeyword,
            $supplierKeyword,
            $searchKeyword,
            $phoneType,
            $bidOwnerMobile,
            $provinceCode,
            $cityCode,
            $areaCode,
            $scoreWeight
        );

        $query = BigDataContactModel::find()->query($condition);
        //var_dump(json_encode($query, JSON_UNESCAPED_UNICODE));
        //exit();
        $query->orderBy(['_score' => SORT_DESC, 'data_time' => SORT_DESC,]);
        if (!empty($fieldes)) {
            $query->source($fieldes);
        }

        $total = $query->count();
        //分页处理
        $query->offset(($page - 1) * $pageSize)->limit($pageSize);
        $data = $query->asArray()->all();
        $result = ['total' => $total, 'list' => []];
        foreach ($data as $dk => $dv) {
            $tmp = $dv['_source'];
            $tmp['_score'] = $dv['_score'];
            $result['list'][] = $tmp;
        }
        return $result;
    }

    /** 联系人列表：构造查询条件
     * @param array $companyName
     * @param array $organizingCode
     * @param string $currentCompanyName
     * @param string $currentOrganizingCode
     * @param array $subscriptProvinceCode
     * @param array $subscriptCityCode
     * @param string $isDeveloper
     * @param string $isSupplier
     * @param array $bidKeyword
     * @param array $supplierKeyword
     * @param array $searchKeyword
     * @param string $phoneType
     * @param string $bidOwnerMobile
     * @param array $provinceCode
     * @param array $cityCode
     * @return array
     */
    private function constructConditionContactRecommend(
        $id = [],
        $companyName = [],
        $organizingCode = [],
        $currentCompanyName = '',
        $currentOrganizingCode = '',
        $subscriptProvinceCode = [],
        $subscriptCityCode = [],
        $isDeveloper = '',
        $isSupplier = '',
        $bidKeyword = [],
        $supplierKeyword = [],
        $searchKeyword = [],
        $phoneType = [],
        $bidOwnerMobile = '',
        $provinceCode = [],
        $cityCode = [],
        $areaCode = [],
        $scoreWeight = ''
    )
    {
        $query = [];
        $slop = !empty(\Yii::$app->params['CommonDataDeveloperSlop']) ? \Yii::$app->params['CommonDataDeveloperSlop'] : 2;
        $must = [];
        $query['function_score']['query']['bool']['must'] = &$must;

        //搜索
        if (!empty($searchKeyword)) {
            $keywordShould = [];
            $must[] = ['bool' => ['should' => &$keywordShould]];
            foreach ($searchKeyword as $k) {
                $keywordShould[] = [
                    'match_phrase' => ['name' => ["query" => $k, 'slop' => $slop]]
                ];

                $keywordShould[] = [
                    'match_phrase' => ['company_name' => ["query" => $k, 'slop' => $slop]]
                ];

                $keywordShould[] = [
                    'nested' => [
                        'path' => 'cooperation',
                        'query' => ['match_phrase' => ['cooperation.title' => ["query" => $k, 'slop' => $slop]]]
                    ]
                ];
            }
        }

        // 是开发商
        if (!empty($id)) {
            $must[] = ["terms" => ['source_id' => $id]];
        }
        // 是开发商
        if (!empty($isDeveloper)) {
            $must[] = ["term" => ['is_developer' => $isDeveloper]];
        }
        //是供应商
        if (!empty($isSupplier)) {
            $must[] = ["term" => ['is_supplier' => $isSupplier]];
        }

        // 联系方式类型
        if (!empty($phoneType)) {
            $must[] = ["terms" => ['phone_type' => $phoneType]];
        }

        /*$must[] = ["nested" => [
            'path' => 'cooperation',
            'query' => ['term' => ['cooperation.category' => '合作案例']]
        ]];*/

        // 省份
        if (!empty($provinceCode)) {
            $must[] = ["nested" => [
                'path' => 'cooperation',
                'query' => ['terms' => ['cooperation.province_code' => $provinceCode]]
            ]];
        }
        // 城市
        if (!empty($cityCode)) {
            $must[] = ["nested" => [
                'path' => 'cooperation',
                'query' => ['terms' => ['cooperation.city_code' => $cityCode]]
            ]];
        }
        // 区域：省份code放在一起
        if (!empty($areaCode)) {
            $must[] = [
                'bool' => [
                    'should' => [
                        0 => ["nested" => [
                            'path' => 'cooperation',
                            'query' => ['terms' => ['cooperation.province_code' => $areaCode]]
                        ]],
                        1 => ["nested" => [
                            'path' => 'cooperation',
                            'query' => ['terms' => ['cooperation.city_code' => $areaCode]]
                        ]]
                    ]
                ]
            ];
        }

        // 公司过滤，兼容公司名称和信用代码
        if (!empty($companyName) || !empty($organizingCode)) {
            $shouldCompany = [];
            $must[] = ['bool' => ['should' => &$shouldCompany]];
            if (!empty($companyName)) {
                $shouldCompany[] = ["terms" => ['company_name.keyword' => $companyName]];
            }
            //去掉信用代码20230919
            /* if (!empty($organizingCode)) {
                 $shouldCompany[] = ["terms" => ['organizing_code' => $organizingCode]];
             }*/

        }

        //自定义评分规则,如果接口有指定权重类型，则按接口为准，否则，按默认权重规则
        if (empty($scoreWeight)) {
            if (!empty($isDeveloper)) {//开发商联系人得分权重配置
                $scoreType = ScoreCondition::DEVELOPER_CONTACT;
            } elseif (!empty($isSupplier)) {//供应商联系人得分权重配置
                $scoreType = ScoreCondition::SUPPLIER_CONTACT;
            } else {//默认开发商
                $scoreType = ScoreCondition::DEVELOPER_CONTACT;
            }
        } else {
            $scoreType = $scoreWeight;
        }

        $scoreCondition = new ScoreCondition($scoreType);
        if (empty($scoreWeight)) {//默认情况
            $scoreCondition->isSupplier = $isSupplier;
            $scoreCondition->isDeveloper = $isDeveloper;
        } else {
            //有指定评分规则：single_customer场景
            if ($scoreWeight == ScoreCondition::DEVELOPER_CONTACT) {
                $scoreCondition->isDeveloper = 1;
            }
        }
        $scoreCondition->lastOneYear = strtotime("-1 year");
        $scoreCondition->phone_type = '手机';
        $scoreCondition->supplierKeyword = $supplierKeyword;
        $scoreCondition->subscriptProvinceCode = $subscriptProvinceCode;
        $scoreCondition->subscriptCityCode = $subscriptCityCode;
        $scoreCondition->currentOrganizingCode = $currentOrganizingCode;
        $scoreCondition->currentCompanyName = $currentCompanyName;
        $scoreCondition->bidKeyword = $bidKeyword;
        $scoreCondition->bidOwnerMobile = $bidOwnerMobile;

        $query['function_score']['functions'] = $this->getFunctionList($scoreCondition);
        $query['function_score']['score_mode'] = 'sum'; //功能分数累加
        $query['function_score']['boost_mode'] = 'replace'; //查询分数被替换，仅使用功能分数


        return $query;
    }


    /** 合作单位列表
     * @param array $companyName
     * @param array $organizingCode
     * @param array $subscriptProvinceCode
     * @param array $subscriptCityCode
     * @param string $isSupplier
     * @param array $supplierKeyword
     * @param array $searchKeyword
     * @param int $page
     * @param int $pageSize
     * @return array
     */
    public function getCooperation(
        $companyName = [],
        $organizingCode = [],
        $currentCompanyName = '',
        $currentOrganizingCode = '',
        $subscriptProvinceCode = [],
        $subscriptCityCode = [],
        $isDeveloper = '',
        $isSupplier = '',
        $bidKeyword = [],
        $supplierKeyword = [],
        $searchKeyword = [],
        $phoneType = '',
        $bidOwnerMobile = '',
        $provinceCode = [],
        $cityCode = [],
        $page = 1,
        $pageSize = 20
    )
    {

        $condition = $this->constructConditionCooperation(
            $companyName,
            $organizingCode,
            $subscriptProvinceCode,
            $subscriptCityCode,
            $isSupplier,
            $supplierKeyword,
            $searchKeyword
        );

        $groupAggregations = $this->getGroupAggregations();

        $query = (new EsQuery())
            ->from(BigDataContactModel::index(), BigDataContactModel::type())
            ->query($condition);
        $query->addAggs('group_by_company', $groupAggregations);

        $highlight = [
            'pre_tags' => ['<em class="_high">'],
            'post_tags' => ['</em>'],
            "fields" => [
                "company_name" => new \stdClass(),
                "cooperation.title" => new \stdClass(),
            ]
        ];
        $query->highlight($highlight);
        $data = $query->createCommand()->search();
        \yii::info("contact-result", json_encode($data, JSON_UNESCAPED_UNICODE));
        //数据处理
        $total = isset($data['aggregations']['group_by_company']['buckets']) ? count($data['aggregations']['group_by_company']['buckets']) : 0;
        $result = ['total' => $total, 'list' => []];
        if ($total == 0) {
            return $result;
        }

        $supplierCompany = [];
        $offset = ($page - 1) * $pageSize;
        $end = $offset + $pageSize;
        $supplierName = [];
        foreach ($data['aggregations']['group_by_company']['buckets'] as $dk => $dv) {
            if ($dk >= $offset && $dk <= $end) {
                $item = [
                    'cooperation_company_name' => $dv['key'],
                    'cooperation_organizing_code' => '',
                    'doc_count' => $dv['doc_count'],
                    '_max_score' => $dv['max_score']['value']
                ];
                $supplierName[] = $dv['key'];
                $supplierCompany[] = $item;
            }
        }
        //获取联系人
        $pageSize = 10000;
        $contactList = $this->getRecommend($supplierName, [], $currentCompanyName, $currentOrganizingCode, $subscriptProvinceCode, $subscriptCityCode, '', 1, $bidKeyword, $supplierKeyword, [], '', '', [], [], 1, [], '', $pageSize);
        $contactTotal = [];
        if ($contactList['total'] > 0) {
            $contactList = ArrayUtils::arrayIndex($contactList['list'], 'company_name');
            foreach ($contactList as $key => $value) {
                $topTwoContact = [];
                foreach ($value as $ck => $cv) {
                    if ($ck <= 1) {
                        $topTwoContact[] = $cv;
                    }
                }
                $contactList[$key] = $topTwoContact;
                $contactTotal[$key] = count($value);
            }
        }
        //设置合作单位列表的联系人
        foreach ($supplierCompany as $companyKey => &$companyValue) {
            $companyValue['contact'] = $contactList[$companyValue['cooperation_company_name']];
            $companyValue['contact_cnt'] = isset($contactTotal[$companyValue['cooperation_company_name']]) ? $contactTotal[$companyValue['cooperation_company_name']] : 0;
        }
        $result['list'] = $supplierCompany;
        return $result;
    }

    /** 合作单位：构建 group by聚合语句
     * @return array
     */
    private function getGroupAggregations()
    {
        return [
            'terms' => [
                'field' => 'company_name.keyword',
                'size' => 10000, //最多取1万，然后应用端分页
                'order' => [
                    'max_score' => 'desc'
                ]
            ],
            'aggregations' => [
                'max_score' => [
                    'max' => [
                        'script' => [
                            'source' => '_score' //联系人的最高分，即合作单位的排序得分
                        ]
                    ]
                ],
                'top_hits' => [
                    'top_hits' => [
                        'size' => 2,
                        '_source' => ['includes' => ["company_name", "data_time", "phone_number", "organizing_code", "position", "name", "cooperation.cooperation_company_name", "cooperation.cooperation_organizing_code", "cooperation.title", "cooperation.province_code", "cooperation.city_code"]],
                        'sort' => [
                            '_score' => 'desc'
                        ]
                    ]
                ]
            ]
        ];
    }

    /** 合作单位：构造查询条件
     * @param array $companyName
     * @param array $organizingCode
     * @param array $subscriptProvinceCode
     * @param array $subscriptCityCode
     * @param string $isSupplier
     * @param array $supplierKeyword
     * @param array $searchKeyword
     * @return array
     */
    private function constructConditionCooperation(
        $companyName = [],
        $organizingCode = [],
        $subscriptProvinceCode = [],
        $subscriptCityCode = [],
        $isSupplier = '',
        $supplierKeyword = [],
        $searchKeyword = []
    )
    {
        $query = [];
        $slop = !empty(\Yii::$app->params['CommonDataDeveloperSlop']) ? \Yii::$app->params['CommonDataDeveloperSlop'] : 2;
        $must = [];
        $query['function_score']['query']['bool']['must'] = &$must;

        //1、function_score->query 检索
        if (!empty($searchKeyword)) {
            $keywordShould = [];
            $must[] = ['bool' => ['should' => &$keywordShould]];
            foreach ($searchKeyword as $k) {
                $keywordShould[] = [
                    'match_phrase' => ['company_name' => ["query" => $k, 'slop' => $slop]]
                ];

                $keywordShould[] = [
                    'nested' => [
                        'path' => 'cooperation',
                        'query' => ['match_phrase' => ['cooperation.title' => ["query" => $k, 'slop' => $slop]]]
                    ]
                ];
            }
        }

        //是供应商
        if (!empty($isSupplier)) {
            $must[] = ["term" => ['is_supplier' => $isSupplier]];
        }

        // 公司过滤，兼容公司名称和信用代码
        if (!empty($companyName) || !empty($organizingCode)) {
            $shouldCompany = [];
            $must[] = ['nested' => ['path' => 'cooperation', 'query' => [
                'bool' => ['should' => &$shouldCompany]
            ]]];
            if (!empty($companyName)) {
                $shouldCompany[] = ["terms" => ['cooperation.cooperation_company_name.keyword' => $companyName]];
            }
            if (!empty($organizingCode)) {
                $shouldCompany[] = ["terms" => ['cooperation.cooperation_organizing_code' => $organizingCode]];
            }

        }

        //2、function_score->function_score 对联系人进行，自定义评分
        $scoreType = ScoreCondition::COOPERATION_CONTACT;
        $scoreCondition = new ScoreCondition($scoreType);
        $scoreCondition->isSupplier = $isSupplier;
        $scoreCondition->lastOneYear = strtotime("-1 year");
        $scoreCondition->phone_type = '手机';
        $scoreCondition->supplierKeyword = $supplierKeyword;
        $scoreCondition->subscriptProvinceCode = $subscriptProvinceCode;
        $scoreCondition->subscriptCityCode = $subscriptCityCode;
        $query['function_score']['functions'] = $this->getFunctionList($scoreCondition);
        $query['function_score']['score_mode'] = 'sum'; //功能分数累加
        $query['function_score']['boost_mode'] = 'replace'; //查询分数被替换，仅使用功能分数

        return $query;
    }

    //自定义评分规则
    private function getFunctionList(ScoreCondition $condition)
    {
        $functionList = [];
        //1、关键词匹配+100分: 开发商，取招标订阅关键词；工程单位，取工程单位订阅关键词
        // terms 分词有些匹配不上
        /*if (!empty($condition->isDeveloper) && !empty($condition->bidKeyword)) {
            $functionList[] = [
                'filter' => ['nested' => [
                    'path' => 'cooperation',
                    'query' => [
                        'terms' => [
                            'cooperation.title' => $condition->bidKeyword
                        ]
                    ]
                ]], "weight" => $condition->keywordWeight
            ];
        }
        if (!empty($condition->isSupplier) && !empty($condition->supplierKeyword)) {
            $functionList[] = [
                'filter' => ['nested' => [
                    'path' => 'cooperation',
                    'query' => [
                        'terms' => [
                            'cooperation.title' => $condition->supplierKeyword
                        ]
                    ]
                ]], "weight" => $condition->keywordWeight
            ];
        }*/
        if (!empty($condition->isDeveloper) && !empty($condition->bidKeyword)) {
            $functionList[] = [
                'filter' => ['nested' => [
                    'path' => 'cooperation',
                    'query' => [
                        'bool' => [
                            'must' => [
                                0 => [
                                    'query_string' => [
                                        'query' => join(" ", $condition->bidKeyword),
                                        'default_field' => 'cooperation.title',
                                        "analyzer" => "ik_smart"//按最粗粒度分词
                                    ]
                                ],
                                1 => [
                                    'term' => [
                                        'cooperation.category' => [
                                            'value' => '历史招标'
                                        ]
                                    ]
                                ]
                            ]
                        ]
                    ]
                ]], "weight" => $condition->keywordWeight
            ];
        }
        if (!empty($condition->isSupplier) && !empty($condition->supplierKeyword)) {
            $functionList[] = [
                'filter' => ['nested' => [
                    'path' => 'cooperation',
                    'query' => [
                        'bool' => [
                            'must' => [
                                0 => [
                                    'query_string' => [
                                        'query' => join(",", $condition->supplierKeyword),
                                        'default_field' => 'cooperation.title',
                                        "analyzer" => "ik_smart"//按最粗粒度分词
                                    ]
                                ],
                                1 => [
                                    'term' => [
                                        'cooperation.category' => [
                                            'value' => '合作案例'
                                        ]
                                    ]
                                ]
                            ]
                        ]
                    ]
                ]], "weight" => $condition->keywordWeight
            ];
        }
        //2、匹配订阅地区+50分
        $subscriptAreaShould = [];
        if (!empty($condition->subscriptProvinceCode)) {
            $subscriptAreaShould[] = [
                'terms' => [
                    'cooperation.province_code' => $condition->subscriptProvinceCode
                ]
            ];
        }
        if (!empty($condition->subscriptCityCode)) {
            $subscriptAreaShould[] = [
                'terms' => [
                    'cooperation.city_code' => $condition->subscriptCityCode
                ]
            ];
        }
        $category = '合作案例';//默认是合作案例
        if (!empty($condition->isDeveloper) && !empty($condition->bidKeyword)) {
            $category = '历史招标';
        }
        if (!empty($condition->subscriptProvinceCode) || !empty($condition->subscriptCityCode)) {
            $functionList[] = [
                'filter' => ['nested' => [
                    'path' => 'cooperation',
                    'query' => [
                        'bool' => [
                            'must' => [
                                0 => [
                                    'bool' => [
                                        'should' => &$subscriptAreaShould
                                    ]
                                ],
                                1 => [
                                    'term' => [
                                        'cooperation.category' => [
                                            'value' => $category
                                        ]
                                    ]
                                ]
                            ]
                        ]
                    ]
                ]], "weight" => $condition->areaWeight
            ];
        }

        //3、联系人所在公司为打开的客户详情页企业的联系人 +50分
        if (!empty($condition->currentCompanyName)) {
            $functionList[] = [
                'filter' => ['term' => ['company_name.keyword' => $condition->currentCompanyName]], "weight" => $condition->currentCompanyWeight
            ];
        } else if (!empty($condition->currentOrganizingCode)) {
            $functionList[] = [
                'filter' => ['term' => ['organizing_code' => $condition->currentOrganizingCode]], "weight" => $condition->currentCompanyWeight
            ];
        }

        //4、联系方式为手机+50分
        if (!empty($condition->phone_type)) {
            $functionList[] = [
                'filter' => ['term' => ['phone_type' => $condition->phone_type]], //手机、座机
                "weight" => $condition->phoneTypeWeight
            ];
        }

        //5、联系人为近一年更新 +100分  。  /1000 是毫秒转为秒，-28800是8个小时时区差
        if (!empty($condition->lastOneYear)) {
            $functionList[] = [
                'script_score' => ['script' => [
                    'source' => "doc['data_time'].value.toInstant().toEpochMilli()/1000-28800>" . $condition->lastOneYear . "?" . $condition->lastOneYearWeight . ":0"
                ]]
            ];
        }


        //6、联系人是招标负责人 加很大的分为了排到第一位，500分
        if (!empty($condition->bidOwnerMobile)) {
            $functionList[] = [
                'filter' => ['term' => ['phone_number' => $condition->bidOwnerMobile]],
                "weight" => $condition->bidOwnerMobileWeight
            ];
        }
        return $functionList;
    }

    public function guessNames($keyword, $pageSize)
    {
        $page = 1;

        $query = [];
        if (!empty($keyword)) {
            $query['function_score']['query']['bool']['must'][] = [
                'match_phrase' => ['supplier_name' => $keyword]
            ];
        }

        $query = BigDataSaasSupplierModel::find()
            ->query($query);

        //高亮处理
        $highlight = [
            'pre_tags' => ['<em class="_high">'],
            'post_tags' => ['</em>'],
            "fields" => [
                "supplier_name" => new \stdClass(),
            ]
        ];
        $query->highlight($highlight);
        $query->orderBy(['_score' => SORT_DESC]);

        //分页处理
        $query->offset(($page - 1) * $pageSize)->limit($pageSize);
        $data = $query->asArray()->all();
        //数据处理
        $result = [];
        foreach ($data as $dv) {
            $item = array();
            $tmp = $dv['_source'];
            $tmp['nameSuggest'] = $tmp['supplier_name'];
            if (!empty($dv['highlight'])) {
                foreach ($dv['highlight'] as $key => $value) {
                    $tmp[$key . 'HL'] = isset($value[0]) ? $value[0] : '';
                }
            }
            $item['title'] = $tmp['supplier_name'];
            $item['titleHL'] = $tmp['supplier_nameHL'];
            $result[] = $item;
        }
        return $result;
    }


    public function formatContact($data)
    {
        $return_params = [
            'pulsar_time' => 'string',
            'id' => 'string',
            'phone_number' => 'string',
            'phone_type' => 'string',
            'name' => 'string',
            'company_name' => 'string',
            'organizing_code' => 'string',
            'position' => 'string',
            'email' => 'string',
            'data_time' => 'string',
            'is_supplier' => 'string',
            'is_developer' => 'string',
            'cooperation_cnt' => 'int',
            'cooperation_subscript_cnt' => 'int',
            'bidding_cnt' => 'int',
            'bidding_subscript_cnt' => 'int',
            'is_recommend' => 'int',
            'purchase_owner' => 'string',
            'source_id' => 'string',
            'cooperation' => 'array',
            'nameHL' => 'string',
            'company_nameHL' => 'string',
            'cooperation.titleHL' => 'string',
            '_score' => 'int'
        ];

        $result = [];
        foreach ($return_params as $rk => $rv) {
            $tmp = isset($data[$rk]) ? $data[$rk] : '';
            $tmp = $tmp === '1990-01-01 00:00:00' ? '' : $tmp;
            if ($rv == 'int') {
                $result[$rk] = (int)$tmp;
            } elseif ($rv == 'array') {
                $result[$rk] = empty($tmp) ? [] : $tmp;
            } else {
                $result[$rk] = $tmp;
            }
            //$result[$rk] = $rv == 'int' ? (int)$tmp : $tmp;
        }
        return $result;
    }

    public function formatCooperation($data)
    {
        $return_params = [
            'title' => 'string',
            'cooperation_company_name' => 'string',
            'cooperation_organizing_code' => 'string',
            'source_id' => 'string',
            'province' => 'string',
            'province_code' => 'string',
            'city' => 'string',
            'city_code' => 'string',
            'cooperation_time' => 'string',
            'category' => 'string',
            'source_type' => 'string',
            "weight" => 'int',
            'titleHL' => 'string'
        ];

        $result = [];
        foreach ($return_params as $rk => $rv) {
            $tmp = isset($data[$rk]) ? $data[$rk] : '';
            $tmp = $tmp === '1990-01-01 00:00:00' ? '' : $tmp;
            $result[$rk] = $rv == 'int' ? (int)$tmp : $tmp;
        }
        return $result;
    }

    public function getRadarContactList(
        $companyName = [],
        $organizingCode = [],
        $subscriptAreaCode = [],
        $bidKeyword = [],
        $isDeveloper = '',
        $isSupplier = ''
    )
    {
        $condition = $this->constructGetRadarContactCondition($companyName, $organizingCode, $subscriptAreaCode,
            $bidKeyword, $isDeveloper, $isSupplier);
//        $groupAggregations = $this->getRadarContactGroupAggregations();
        $query = (new EsQuery())
            ->from(BigDataContactModel::index(), BigDataContactModel::type())
            ->query($condition);
//        $query->addAggs('group_by_company', $groupAggregations);
        $query->orderBy(['_score' => SORT_DESC, "data_time" => SORT_DESC]);
        $query->limit(10000);//取全量，所以传个较大值
        $data = $query->createCommand()->search();
        $result = [];
//        foreach ($data['aggregations']['group_by_company']['buckets'] as $dv) {
//            foreach ($dv["top_hits"]["hits"]["hits"] as $hits) {
//                $result[] = $hits["_source"];
//            }
//        }
        //每家公司取2个联系人
        $companyCount = [];
        foreach ($data["hits"]["hits"] as $item) {
            $tmp = $item["_source"];
            if (!isset($companyCount[$tmp["organizing_code"]])) {
                $companyCount[$tmp["organizing_code"]] = 1;
                $result[] = $tmp;
            } else {
                $companyCount[$tmp["organizing_code"]]++;
                if ($companyCount[$tmp["organizing_code"]] <= 2) {
                    $result[] = $tmp;
                }
            }
        }

        foreach ($result as &$value) {
            //1、是否匹配订阅
            $isKeywordMatch = false;
            if (!empty($value['cooperation'])) {
                foreach ($value['cooperation'] as &$cooperationV) {
                    if (!empty($isDeveloper) && !empty($bidKeyword)) {
                        foreach ($bidKeyword as $keywordValue) {
                            if (mb_strpos($cooperationV['title'], $keywordValue) !== false && $cooperationV['category'] == '历史招标') {
                                $isKeywordMatch = true;
                            }
                        }
                    }
                }
            }
            //合作案例做多展示2条
            $newCooperation = [];
            if (!empty($value['cooperation'])) {
                foreach ($value['cooperation'] as $cooperationK2 => $cooperationV2) {
                    if ($cooperationK2 <= 1) {
                        $newCooperation[] = $cooperationV2;
                    }
                }
                $value['cooperation'] = $newCooperation;
            }

            //是否推荐
            $lastYearTimeStamp = strtotime("-1 year");
            if ($value['phone_type'] == '手机' && strtotime($value['data_time']) >= $lastYearTimeStamp && $isKeywordMatch) {
                $value['is_recommend'] = 1;
            } else {
                $value['is_recommend'] = 0;
            }
        }

        return $result;
    }

    private function getRadarContactGroupAggregations()
    {
        return [
            'terms' => [
                'field' => 'company_name.keyword',
                'size' => 10000, //最多取1万，然后应用端分页
                'order' => [
                    'max_score' => 'desc'
                ]
            ],
            'aggregations' => [
                'max_score' => [
                    'max' => [
                        'script' => [
                            'source' => '_score' //联系人的最高分，即合作单位的排序得分
                        ]
                    ]
                ],
                'top_hits' => [
                    'top_hits' => [
                        'size' => 2,
                        //展示全部字段
                        //'_source' => ['includes' => ["source_id", "company_name", "phone_number", "organizing_code", "position", "name"]],
                        'sort' => [
                            '_score' => 'desc',
                            "data_time" => "desc"

                        ]
                    ]
                ]
            ]
        ];
    }

    private function constructGetRadarContactCondition(
        $companyName = [],
        $organizingCode = [],
        $subscriptAreaCode = [],
        $bidKeyword = [],
        $isDeveloper = '',
        $isSupplier = ''
    ): array
    {
        $must = [];

        // 公司过滤，兼容公司名称和信用代码
        if (!empty($companyName) || !empty($organizingCode)) {
            $shouldCompany = [];
            if (!empty($companyName)) {
                $shouldCompany[] = ["terms" => ['company_name.keyword' => $companyName]];
            }
            if (!empty($organizingCode)) {
                $shouldCompany[] = ["terms" => ['organizing_code' => $organizingCode]];
            }
            if (!empty($shouldCompany)) {
                $must[] = ['bool' => ['should' => $shouldCompany]];
            }
        }

        // 是开发商
        if (!empty($isDeveloper)) {
            $must[] = ["term" => ['is_developer' => $isDeveloper]];
        }
        //是供应商
        if (!empty($isSupplier)) {
            $must[] = ["term" => ['is_supplier' => $isSupplier]];
        }

        //自定义评分规则,默认为开发商
        $scoreType = ScoreCondition::DEVELOPER_CONTACT;
        if (!empty($isSupplier)) {//供应商联系人得分权重配置
            $scoreType = ScoreCondition::SUPPLIER_CONTACT;
        }
        $scoreCondition = new ScoreCondition($scoreType);
        $scoreCondition->isSupplier = $isSupplier;
        $scoreCondition->isDeveloper = $isDeveloper;
        $scoreCondition->lastOneYear = strtotime("-1 year");
        $scoreCondition->phone_type = '手机';
        $scoreCondition->subscriptProvinceCode = $subscriptAreaCode;
        $scoreCondition->subscriptCityCode = $subscriptAreaCode;
        $scoreCondition->bidKeyword = $bidKeyword;

        $query = [];
        $query['function_score']['functions'] = $this->getFunctionList($scoreCondition);
        $query['function_score']['score_mode'] = 'sum'; //功能分数累加
        $query['function_score']['boost_mode'] = 'replace'; //查询分数被替换，仅使用功能分数
        $query['function_score']['query']['bool']['must'] = $must;
        return $query;
    }


    /**  合作单位列表新版，有点性能问题
     * @param array $companyList
     * @param string $currentCompanyName
     * @param string $currentOrganizingCode
     * @param array $subscriptProvinceCode
     * @param array $subscriptCityCode
     * @param string $isDeveloper
     * @param string $isSupplier
     * @param array $bidKeyword
     * @param array $supplierKeyword
     * @param array $searchKeyword
     * @param string $phoneType
     * @param string $bidOwnerMobile
     * @param array $provinceCode
     * @param array $cityCode
     * @param int $page
     * @param int $pageSize
     * @return mixed
     */
    public function getCooperationNew(
        $id = [],
        $companyList = [],
        $currentCompanyName = '',
        $currentOrganizingCode = '',
        $subscriptProvinceCode = [],
        $subscriptCityCode = [],
        $isDeveloper = '',
        $isSupplier = '',
        $bidKeyword = [],
        $supplierKeyword = [],
        $searchKeyword = [],
        $phoneType = '',
        $bidOwnerMobile = '',
        $provinceCode = [],
        $cityCode = [],
        $page = 1,
        $pageSize = 20
    )
    {
        //获取联系人
        $contactPageSize = 10000;
        $companyName = $organizingCode = [];
        foreach ($companyList as $companyValue) {
            if (!empty($companyValue['company_name'])) {
                $companyName[] = $companyValue['company_name'];
            }
            if (!empty($companyValue['organizing_code'])) {
                $organizingCode[] = $companyValue['organizing_code'];
            }
        }

        $contactList = $this->getRecommend($id, $companyName, $organizingCode, $currentCompanyName, $currentOrganizingCode, $subscriptProvinceCode, $subscriptCityCode, '', 1, $bidKeyword, $supplierKeyword, $searchKeyword, '', '', [], [], [], '', 1, $contactPageSize);
        $contactTotal = [];
        $companyScore = [];
        if ($contactList['total'] > 0) {
            $contactList = ArrayUtils::arrayIndex($contactList['list'], 'company_name');
            foreach ($contactList as $key => $value) {
                $topTwoContact = [];
                if (count($value) > 0) {
                    foreach ($value as $ck => $cv) {
                        if ($ck <= 1) {
                            $topTwoContact[] = $cv;
                        }

                        if ($ck == 0) {
                            $companyScore[$key] = $cv['_score'];
                        }
                    }
                }
                $contactList[$key] = $topTwoContact;
                $contactTotal[$key] = count($value);
            }
        }

        //设置合作单位列表的联系人
        $newCompany = [];
        foreach ($companyList as $companyKey => &$companyValue) {
            $newCompany[] = [
                'cooperation_company_name' => $companyValue['company_name'],
                'cooperation_organizing_code' => $companyValue['organizing_code'],
                '_max_score' => !empty($companyValue['company_name']) && isset($companyScore[$companyValue['company_name']]) ? $companyScore[$companyValue['company_name']] : 0,
                'contact' => !empty($companyValue['company_name']) && isset($contactList[$companyValue['company_name']]) ? $contactList[$companyValue['company_name']] : [],
                'contact_cnt' => !empty($companyValue['company_name']) && isset($contactTotal[$companyValue['company_name']]) ? $contactTotal[$companyValue['company_name']] : 0,
            ];

        }
        array_multisort(array_column($newCompany, '_max_score'), SORT_DESC, $newCompany);

        //分页
        $pageCompany = [];
        $offset = ($page - 1) * $pageSize;
        $end = $offset + $pageSize - 1;

        foreach ($newCompany as $dk => $dv) {
            if ($dk >= $offset && $dk <= $end) {
                $pageCompany[] = $dv;
            }
        }

        $result['list'] = $pageCompany;
        $result['total'] = count($newCompany);
        return $result;
    }

    /** 合作单位列表新版，继续优化：查询拆分2次
     * @param array $companyName
     * @param array $organizingCode
     * @param array $subscriptProvinceCode
     * @param array $subscriptCityCode
     * @param string $isSupplier
     * @param array $supplierKeyword
     * @param array $searchKeyword
     * @param int $page
     * @param int $pageSize
     * @return array
     */
    public function getCooperationNewFast(
        $id = [],
        $companyList = [],
        $currentCompanyName = '',
        $currentOrganizingCode = '',
        $subscriptProvinceCode = [],
        $subscriptCityCode = [],
        $isDeveloper = '',
        $isSupplier = '',
        $bidKeyword = [],
        $supplierKeyword = [],
        $searchKeyword = [],
        $phoneType = '',
        $bidOwnerMobile = '',
        $provinceCode = [],
        $cityCode = [],
        $page = 1,
        $pageSize = 20
    )
    {
        //获取联系人
        $contactPageSize = 10000;
        $companyName = $organizingCode = [];
        foreach ($companyList as $companyValue) {
            if (!empty($companyValue['company_name'])) {
                $companyName[] = $companyValue['company_name'];
            }
            if (!empty($companyValue['organizing_code'])) {
                $organizingCode[] = $companyValue['organizing_code'];
            }
        }
        $fieldes = ['company_name'];
        $contactList = $this->getRecommendSingle($id, $companyName, [], $currentCompanyName, $currentOrganizingCode, $subscriptProvinceCode, $subscriptCityCode, '', 1, $bidKeyword, $supplierKeyword, $searchKeyword, '', '', [], [], [], '', 1, $contactPageSize, $fieldes);
        $companyScore = [];
        if ($contactList['total'] > 0) {
            $contactList = ArrayUtils::arrayIndex($contactList['list'], 'company_name');
            foreach ($contactList as $key => $value) {
                if (count($value) > 0) {
                    foreach ($value as $ck => $cv) {
                        if ($ck == 0) {
                            $companyScore[$key] = $cv['_score'];
                        }
                    }
                }

            }
        }

        //设置合作单位列表的联系人
        $newCompany = [];
        foreach ($companyList as $companyKey => &$companyValue) {
            $newCompany[] = [
                'cooperation_company_name' => $companyValue['company_name'],
                'cooperation_organizing_code' => $companyValue['organizing_code'],
                '_max_score' => !empty($companyValue['company_name']) && isset($companyScore[$companyValue['company_name']]) ? $companyScore[$companyValue['company_name']] : 0,
            ];

        }
        array_multisort(array_column($newCompany, '_max_score'), SORT_DESC, $newCompany);

        //分页
        $pageCompany = [];
        $offset = ($page - 1) * $pageSize;
        $end = $offset + $pageSize - 1;

        $pageCompanyName = [];
        foreach ($newCompany as $dk => $dv) {
            if ($dk >= $offset && $dk <= $end) {
                $pageCompany[] = $dv;
                $pageCompanyName[] = $dv['cooperation_company_name'];
            }
        }
        //第1页公司，去获取联系人
        if (!empty($pageCompanyName)) {//公司存在，再去查询联系人
            $contactListPage = $this->getRecommend([], $pageCompanyName, [], $currentCompanyName, $currentOrganizingCode, $subscriptProvinceCode, $subscriptCityCode, '', 1, $bidKeyword, $supplierKeyword, $searchKeyword, '', '', [], [], [], '', 1, $contactPageSize);
            $contactArr = [];
            $contactTotal = [];

            if ($contactListPage['total'] > 0) {
                $contactListPage = ArrayUtils::arrayIndex($contactListPage['list'], 'company_name');

                foreach ($contactListPage as $keyPage => &$valuePage) {
                    $topTwoContact = [];
                    if (count($valuePage) > 0) {
                        foreach ($valuePage as $ckPage => $cvPage) {
                            if ($ckPage <= 1) {
                                $topTwoContact[] = $cvPage;
                            }
                        }
                    }
                    $contactArr[$keyPage] = $topTwoContact;
                    $contactTotal[$keyPage] = count($valuePage);
                }
            }

            foreach ($pageCompany as &$item) {
                //联系人数量不在这里计算，从sr取指标 20231030
                //$item['contact_cnt'] = !empty($item['cooperation_company_name']) && isset($contactTotal[$item['cooperation_company_name']]) ? $contactTotal[$item['cooperation_company_name']] : 0;
                $item['contact'] = !empty($item['cooperation_company_name']) && isset($contactArr[$item['cooperation_company_name']]) ? $contactArr[$item['cooperation_company_name']] : [];

            }
        }

        $result['list'] = $pageCompany;
        $result['total'] = count($newCompany);
        return $result;
    }
}